﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace UtilZ.Dotnet.Ex.DataStruct
{
    /// <summary>
    /// 线程安全列表
    /// </summary>
    /// <typeparam name="T">集合数据类型</typeparam>
    [Serializable]
    public class ConcurrentList<T> : ICollection<T>
    {
        /// <summary>
        /// 内部集合 
        /// </summary>
        private readonly List<T> _items = null;


        /// <summary>
        /// 构造函数
        /// </summary>
        public ConcurrentList()
        {
            this._items = new List<T>();
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="collection">初始化集合</param>
        public ConcurrentList(IEnumerable<T> collection)
        {
            this._items = new List<T>(collection);
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="capacity">初始容量</param>
        public ConcurrentList(int capacity)
        {
            this._items = new List<T>(capacity);
        }


        /// <summary>
        /// 线程锁
        /// </summary>
        public readonly object SyncRoot = new object();

        /// <summary>
        /// 获取集合中包含的元素数
        /// </summary>
        public int Count
        {
            get
            {
                lock (this.SyncRoot)
                {
                    return this._items.Count;
                }
            }
        }

        /// <summary>
        /// 集合是否是只读的
        /// </summary>
        public bool IsReadOnly
        {
            get { return false; }
        }

        /// <summary>
        /// 索引获取或设置值
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns>值</returns>
        public T this[int index]
        {
            get
            {
                lock (this.SyncRoot)
                {
                    return this._items[index];
                }
            }
            set
            {
                lock (this.SyncRoot)
                {
                    this._items[index] = value;
                }
            }
        }


        /// <summary>
        /// 添加对象到集合尾
        /// </summary>
        /// <param name="item"></param>
        public void Add(T item)
        {
            lock (this.SyncRoot)
            {
                this._items.Add(item);
            }
        }

        /// <summary>
        /// 添加对象集合到集合尾
        /// </summary>
        /// <param name="items">对象集合</param>
        public void AddRange(IEnumerable<T> items)
        {
            if (items == null)
            {
                return;
            }

            lock (this.SyncRoot)
            {
                this._items.AddRange(items);
            }
        }

        /// <summary>
        /// 清空集合
        /// </summary>
        public void Clear()
        {
            lock (this.SyncRoot)
            {
                this._items.Clear();
            }
        }

        /// <summary>
        /// 确定某元素是否在集合中
        /// </summary>
        /// <param name="item">指定项</param>
        /// <returns>是否在集合中</returns>
        public bool Contains(T item)
        {
            lock (this.SyncRoot)
            {
                return this._items.Contains(item);
            }
        }

        /// <summary>
        /// 从目标数组的指定索引处开始，将整个 System.Collections.Generic.List`1 复制到兼容的一维数组
        /// </summary>
        /// <param name="array">一维 System.Array，它是从 System.Collections.Generic.List`1 复制的元素的目标。System.Array 必须具有从零开始的索引。</param>
        /// <param name="arrayIndex">array 中从零开始的索引，从此处开始复制</param>
        public void CopyTo(T[] array, int arrayIndex)
        {
            lock (this.SyncRoot)
            {
                this._items.CopyTo(array, arrayIndex);
            }
        }

        /// <summary>
        /// 移除指定的元素
        /// </summary>
        /// <param name="item">指定元素</param>
        /// <returns>移除结果</returns>
        public bool Remove(T item)
        {
            lock (this.SyncRoot)
            {
                return this._items.Remove(item);
            }
        }

        /// <summary>
        /// 移除满足条件的元素
        /// </summary>
        /// <param name="match">删除条件</param>
        /// <returns>移除结果</returns>
        public int RemoveAll(Predicate<T> match)
        {
            lock (this.SyncRoot)
            {
                return this._items.RemoveAll(match);
            }
        }

        /// <summary>
        /// 满足条件的项转换到数组
        /// </summary>
        /// <param name="predicate">条件</param>
        /// <returns>满足条件的项数组</returns>
        public T[] ToArray(Func<T, bool> predicate)
        {
            lock (this.SyncRoot)
            {
                return this._items.Where(predicate).ToArray();
            }
        }



        /// <summary>
        /// 返回循环访问的枚举数(注:遍历时需使用集合的SyncRoot字段加上线程锁)
        /// </summary>
        /// <returns>循环访问的枚举数</returns>
        public IEnumerator<T> GetEnumerator()
        {
            return new ConcurrentListEnumerator(this);
        }

        /// <summary>
        /// GetEnumerator
        /// </summary>
        /// <returns>Enumerator</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }


        /// <summary>
        /// ConcurrentList迭代器
        /// </summary>
        public class ConcurrentListEnumerator : IEnumerator<T>
        {
            private T _current = default(T);
            /// <summary>
            /// 
            /// </summary>
            T IEnumerator<T>.Current
            {
                get { return this._current; }
            }

            /// <summary>
            /// 
            /// </summary>
            object IEnumerator.Current
            {
                get { return this._current; }
            }

            /// <summary>
            /// 
            /// </summary>
            void IDisposable.Dispose()
            {
                GC.SuppressFinalize(this);
            }

            /// <summary>
            /// 内部集合 
            /// </summary>
            private readonly List<T> _items;
            private readonly ConcurrentList<T> _values;


            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="list">迭代的列表</param>
            public ConcurrentListEnumerator(ConcurrentList<T> list)
            {
                this._items = list._items;
                this._values = list;
            }

            private int _index = -1;
            /// <summary>
            /// 
            /// </summary>
            /// <returns></returns>
            bool IEnumerator.MoveNext()
            {
                lock (this._values.SyncRoot)
                {
                    this._index++;
                    if (this._index >= this._items.Count)
                    {
                        return false;
                    }

                    T item = this._items.ElementAt(this._index);

                    while (object.ReferenceEquals(item, this._current))
                    {
                        this._index++;
                        if (this._index >= this._items.Count)
                        {
                            return false;
                        }

                        item = this._items.ElementAt(this._index);
                    }
                    this._current = item;
                    return true;
                }
            }

            void IEnumerator.Reset()
            {
                this._index = -1;
            }

        }
    }


}